package com.to8to.autotask.allocate.newproject;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.to8to.es.util.LogUtil;
import com.to8to.kitt.esb.ZK;

/**
 * AllocateNewProjectTask.java
 * 作 者:atom.liu
 * 版 本:v2.0
 * 日期:2014年11月18日
 * 描 述:分配新项目给客服审核的任务类。
 */
public final class AllocateNewProjectTask implements Runnable
{
    private static final Logger logger = LoggerFactory.getLogger(AllocateNewProjectTask.class);

    /**
     * 是否是自动触发
     */
    private boolean isAutoTrigger = Boolean.TRUE;

    /**
     * 是否分配的是单个
     */
    private boolean isSingle = Boolean.FALSE;

    private int yid;

    private long phoneId;

    private InterProcessMutex distributedLock;

    //本地锁，防止建立过多子节点
    private static final ReentrantLock localLock = new ReentrantLock();

    private static final String LOCK_PATH = "/dlock/allocateSHKF";

    public AllocateNewProjectTask()
    {
        distributedLock = new InterProcessMutex(ZK.ZK_CLIENT, LOCK_PATH);
    }

    public AllocateNewProjectTask(boolean isAutoTrigger)
    {
        this.isAutoTrigger = isAutoTrigger;
        distributedLock = new InterProcessMutex(ZK.ZK_CLIENT, LOCK_PATH);
    }

    /**
     * 执行任务
     */
    @Override
    public void run()
    {
        try
        {
            acquireLocalLock();
            acquireDistributedLock();
            logger.info(String.format("执行分配审核客服...开始！isAutoTrigger : [ %s ] isSingle [ %s ]", isAutoTrigger, isSingle));
            long s1 = System.currentTimeMillis();
            if (isSingle)
                AllocateProjectAlgorithm.allocateSingle(yid, phoneId);
            else
                AllocateProjectAlgorithm.autoAllocate(isAutoTrigger);
            logger.info(String.format("执行分配审核客服...结束！isAutoTrigger : [ %s ] isSingle [ %s ] 共耗时 %s ms", isAutoTrigger, isSingle, (System.currentTimeMillis() - s1)));
        }
        catch (Exception e)
        {
            logger.error("AllocateNewProjectTask.run()异常！{} \n {}", e, LogUtil.logStackTrace(e));
        }
        finally
        {
            releaseDistributedLock();
            releaseLocalLock();
        }
    }

    /**
     * 请求本地锁
     */
    private void acquireLocalLock()
    {
        localLock.lock();
        logger.info("AllocateNewProjectTask 获取本地锁成功！");
    }

    /**
     * 释放本地锁
     */
    private void releaseLocalLock()
    {
        localLock.unlock();
        logger.info("AllocateNewProjectTask 释放本地锁成功！");
    }

    /**
     * 请求分布式锁
     */
    private void acquireDistributedLock() throws Exception
    {
        if (distributedLock.acquire(30, TimeUnit.MINUTES))
        {
            logger.info("AllocateNewProjectTask 获取分布式锁成功！");
        }
        else
        {
            logger.error("AllocateNewProjectTask：30min内获取分布式锁失败，将释放本地锁！");
            releaseLocalLock();
        }
    }

    /**
     * 释放分布式锁
     */
    private void releaseDistributedLock()
    {
        try
        {
            distributedLock.release();
            logger.info("AllocateNewProjectTask 释放分布式锁成功！");
        }
        catch (Exception e)
        {
            logger.error("分布式锁释放异常！{} \n {}", e, LogUtil.logStackTrace(e));
        }
    }

    public boolean isAutoTrigger()
    {
        return isAutoTrigger;
    }

    public void setAutoTrigger(boolean isAutoTrigger)
    {
        this.isAutoTrigger = isAutoTrigger;
    }

    public boolean isSingle()
    {
        return isSingle;
    }

    public void setSingle(boolean isSingle)
    {
        this.isSingle = isSingle;
    }

    public static Logger getLogger()
    {
        return logger;
    }

    public int getYid()
    {
        return yid;
    }

    public void setYid(int yid)
    {
        this.yid = yid;
    }

    public long getPhoneId()
    {
        return phoneId;
    }

    public void setPhoneId(long phoneId)
    {
        this.phoneId = phoneId;
    }
}
